/*
 * Copyright 2010-2012 Susanta Tewari. <freecode4susant@users.sourceforge.net>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package coalescent.br;

import coalescent.br.AMCElement;
import coalescent.br.BRWalker;

/**
 * Contains information during the post-order recursion implementation of a sample onfiguration
 * used to notify the interested listeners.
 *
 * @author Susanta Tewari
 * @version 1.3.0 Dec 3, 2010
 *
 * @param <E>
 * @param <S>
 */
public class BRWCompInfo<E extends Enum<E>, S extends AMCElement<E, S>> {

    /** Field description */
    private final BRWalker<E, S> src;

    /** Field description */
    private final BRWState recursionEventType;

    /** Field description */
    private final S currentConfig;

    /** Field description */
    private S backwardConfig;

    /** Field description */
    private E eventType;

    /**
     * Enumeration of the steps of the post-order recursion implementation of a sample configuration
     * used by the implementation to invoke the corresponding methods on the registered listeners.
     *
     * @author Susanta Tewari
     * @since 1.3.0 Dec 3, 2010
     */
    public enum BRWState {

        BOUNDARY_CONDN,

        /**
         * right before starting to iterate on the events
         */
        STARTING_ITERATING_EVENTS,

        /**
         * Right after the event type has been determined
         */
        ITERATING_SINGLE_EVENT_TYPE, ITERATING_ANCESTRAL_CONFIGS,
        FINISHED_ITERATING_SINGLE_EVENT_TYPE,

        /**
         * right after finished iterating on all events
         */
        FINISHED_ITERATING_EVENTS, FINISHED_RECURSION;
    }

    /**
     *
     * @param src
     * @param recursionEventType the type of the recursion event, indicating a particular point of traversal.
     * @param currentConfig the sample configuration; always non-null
     * @param backwardConfig
     * @param eventType
     */
    public BRWCompInfo(BRWalker<E, S> src, BRWState recursionEventType, S currentConfig,
                       S backwardConfig, E eventType) {

        switch (recursionEventType) {

            case ITERATING_ANCESTRAL_CONFIGS :
                if (backwardConfig == null) {

                    throw new IllegalArgumentException(
                        "ancestral config should NOT be null when the exact recursion event type is "
                        + BRWState.ITERATING_ANCESTRAL_CONFIGS);
                }

                break;

            default :
                if (backwardConfig != null) {

                    throw new IllegalArgumentException(
                        "ancestral event should BE null EXCEPT when the exact recursion event type is "
                        + BRWState.ITERATING_ANCESTRAL_CONFIGS);
                }
        }

        this.src                = src;
        this.recursionEventType = recursionEventType;
        this.currentConfig      = currentConfig;
        this.backwardConfig     = backwardConfig;
        this.eventType          = eventType;
    }

    /**
     * Method description
     *
     *
     * @return
     */
    public E getEventType() {
        return eventType;
    }

    /**
     * Method description
     *
     *
     * @return
     */
    public BRWState getRecursionEventType() {
        return recursionEventType;
    }

    /**
     * Method description
     *
     *
     * @return
     */
    public S getSampleConfig() {
        return src.getRecursion();
    }

    /**
     * Method description
     *
     *
     * @return
     */
    public S getCurrentConfig() {
        return currentConfig;
    }

    /**
     * Method description
     *
     *
     * @return
     */
    public S getAncestralConfig() {
        return backwardConfig;
    }
}
